package com.vhall.component.controller.record;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.vhall.component.controller.record.facade.RecordConsoleFacade;
import com.vhall.component.controller.room.facade.RoomInnerFacade;
import com.vhall.component.entity.audit.vo.AuditRecordResponseVO;
import com.vhall.component.entity.record.RecordEntity;
import com.vhall.component.entity.record.vo.*;
import com.vhall.component.entity.room.dto.RoomsEntityDTO;
import com.vhall.component.entity.room.vo.RoomConsoleListRespVO;
import com.vhall.component.entity.room.vo.RoomConsoleListVO;
import com.vhall.component.framework.common.annotation.VhallComponent;
import com.vhall.component.framework.common.constant.CommonConstant;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.plugin.common.annotation.TokenAuth;
import com.vhall.component.plugin.common.constant.ConstStr;
import com.vhall.component.plugin.common.constant.HttpConstant;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.support.Token;
import com.vhall.component.plugin.common.support.TokenThreadLocal;
import com.vhall.component.service.record.RecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author dongsong
 */
@Slf4j
@VhallComponent
public class RecordConsoleController implements RecordConsoleFacade {

    @Autowired
    private RecordService recordService;

    @Autowired
    private RoomInnerFacade roomInnerFacade;
    /**
     * 限制回放章节打点上限
     */
    public static final int MAX_RECORD_CHAPTER_LIMIT = 100;
    /**
     * 章节打点标题的长度上限
     */
    public static final int MAX_RECORD_CHAPTER_TITLE_LENGTH_LIMIT = 20;

    /**
     * 控制台-房间管理-管理-回放管理-获取回放列表
     *
     * @return
     */
    @TokenAuth
    @Override
    public GetRecordListRspVo list(@Validated GetRecordListReqVo reqVo) {
        return recordService.getRecordList(reqVo);
    }

    /**
     * 控制台-房间管理-管理-回放管理-设置默认回放
     */
    @TokenAuth
    @Override
    public List<Object> setDefaultRecord(@Validated SetDefaultRecordReqVo reqVo) {
        recordService.setDefaultRecord(reqVo);
        return new ArrayList<>();
    }

    @Override
    public Boolean cancelDefaultRecord(String roomId) {
        recordService.cancelDefault(roomId);
        return true;
    }

    /**
     * 控制台-房间管理-管理-回放管理-删除回放
     */
    @TokenAuth
    @Override
    public JSONObject delete(@Validated DeleteRecordReqVo reqVo) {
        return recordService.deleteRecord(reqVo);
    }

    /**
     * 功能描述 视频下载
     */
    @Override
    public JSONObject downRecord(@Validated RecordDownReqVO reqVO) {
        return recordService.downRecord(reqVO);
    }

    /**
     * 功能描述 具有清晰度视频下载
     */
    @Override
    public JSONObject downRecordQuality(@Validated RecordDownQualityReqVO reqVO) {
        String quality = reqVO.getQuality();
        String qualityStr = "same,a,360p,480p,720p";
        String[] qualityArr = qualityStr.split(",");
        if (!Arrays.asList(qualityArr).contains(quality)) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_QUALITY);
        }
        return recordService.downRecordQuality(reqVO);
    }

    /**
     * 功能描述 视频上传-记录保存,只创建记录
     */
    @TokenAuth
    @Override
    public Boolean uploadRecord(@Validated CreateRecordReqVO reqVO) {
        Token account = TokenThreadLocal.getToken();
        reqVO.setAccountId(String.valueOf(account.getAccountId()));
        return recordService.uploadRecord(reqVO);
    }

    /**
     * 功能描述 视频裁剪（保存加导出）
     */
    @TokenAuth
    @Override
    public RecordEntity saveRecord(@Validated CutRecordReqVO reqVO) {
        Token account = TokenThreadLocal.getToken();
        reqVO.setAccountId(String.valueOf(account.getAccountId()));
        String cutSections = reqVO.getCutSections();
        checkCutSections(cutSections);

        String pointSections = reqVO.getPointSections();
        checkPointSections(pointSections);
        return recordService.saveRecord(reqVO);
    }

    private void checkCutSections(String cutSections) {
        JSONArray jsonArray = null;
        try {
            if (StringUtils.isNotBlank(cutSections)) {
                jsonArray = JSON.parseArray(cutSections);
            }
        } catch (Exception e) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }

        if (jsonArray != null && !jsonArray.isEmpty()) {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject object = jsonArray.getJSONObject(i);
                String start = object.get("start").toString();
                String end = object.get("end").toString();
                if (StringUtils.isBlank(start) || StringUtils.isBlank(end)) {
                    throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
                }
                try {
                    if (start.equals(end)) {
                        continue;
                    }
                    if (Integer.parseInt(start) > Integer.parseInt(end)) {
                        throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
                    }
                } catch (Exception e) {
                    throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
                }
            }
        }
    }

    @TokenAuth
    @Override
    public SaveRecordChapterManagementResponseVO saveRecordChapterManagement(SaveRecordChapterManagementRequestVO reqVO) {
        String pointSections = reqVO.getPointSections();
        checkPointSections(pointSections);
        return recordService.saveRecordChapterManagement(reqVO);
    }

    private void checkPointSections(String pointSections) {
        JSONArray pointSectionsJSONArr = null;
        try {
            if (StringUtils.isNotBlank(pointSections)) {
                pointSectionsJSONArr = JSON.parseArray(pointSections);
            }
        } catch (Exception e) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }

        if (pointSectionsJSONArr != null && !pointSectionsJSONArr.isEmpty()) {
            int size = pointSectionsJSONArr.size();
            if (size>MAX_RECORD_CHAPTER_LIMIT) {
                throw new BusinessException(BizErrorCode.RECORD_ADD_CHAPTER_MAX_LIMIT);
            }
            for (int i = 0; i < size; i++) {
                JSONObject object = pointSectionsJSONArr.getJSONObject(i);
                String timePoint = object.get("timePoint").toString();
                String msg = object.get(HttpConstant.MSG).toString();
                if (StringUtils.isBlank(timePoint) || StringUtils.isBlank(msg)) {
                    throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
                }
                if (msg.length() > MAX_RECORD_CHAPTER_TITLE_LENGTH_LIMIT) {
                    throw new BusinessException(BizErrorCode.RECORD_ADD_CHAPTER_NAME_LENGTH_LIMIT);
                }
            }
        }
    }

    @TokenAuth
    @Override
    public SetPointStatusResponseVO setPointStatus(SetPointStatusRequestVO reqVO) {
        return recordService.setPointStatus(reqVO);
    }
    @TokenAuth
    @Override
    public RecordChapterListResponseVO getRecordChapterList(RecordChapterListRequestVO reqVO) {
        return recordService.getRecordChapterList(reqVO);
    }
    /**
     * 回放列表
     */
    @TokenAuth
    @Override
    public JSONObject cutList(@Validated CutListReqVO reqVO) {
        Token account = TokenThreadLocal.getToken();
        reqVO.setAccountId(String.valueOf(account.getAccountId()));
        return recordService.getCutList(reqVO);
    }

    /**
     * 生成回放, Console端手动生成
     */
    @TokenAuth
    @Override
    public RecordEntity cutMergeRecord(@Validated CutMergeRecordReqVO reqVO) {
        Token account = TokenThreadLocal.getToken();
        reqVO.setAccountId(String.valueOf(account.getAccountId()));
        return recordService.cutMergeRecord(reqVO);
    }

    /**
     * 功能描述 获取点播详情
     */
    @TokenAuth
    @Override
    public GetVodInfoRspVO getVodInfo(@Validated GetVodInfoReqVO reqVO) {
        Token account = TokenThreadLocal.getToken();
        if (account == null) {
            throw new BusinessException(BizErrorCode.AUTH_LOGIN_NEEDS);
        }
        GetVodInfoRspVO data = recordService.getVodInfo(reqVO);
        if (data == null) {
            return null;
        }
        RoomsEntityDTO ilInfo = roomInnerFacade.getRoomInfoByIlId(data.getIlId().toString());
        data.setChannelId(ilInfo != null ? ilInfo.getChannelId() : null);
        data.setDurationSecond(Integer.parseInt(data.getDuration()));
        data.setSourceName(StringUtils.isNotBlank(createSourceName(data.getSource())) ? createSourceName(data.getSource()) : "");
        data.setDuration(secToTime(Integer.parseInt(data.getDuration())));
        return data;
    }

    /**
     * 控制台-媒资管理-音视频管理-获取回放列表
     */
    @TokenAuth
    @Override
    public GetUploadListRspVo uploadList(@Validated GetUploadListReqVo reqVo) {
        if (StringUtils.isNotEmpty(reqVo.getSearch())) {
            String search = reqVo.getSearch();
            if (reqVo.getSearch().contains(CommonConstant.UNDERLINE)) {
                search = reqVo.getSearch().replace(CommonConstant.UNDERLINE, "\\" + CommonConstant.UNDERLINE);
            }
            if (reqVo.getSearch().contains(CommonConstant.PERCENT_SIGN)) {
                search = search.replace(CommonConstant.PERCENT_SIGN, "\\" + CommonConstant.PERCENT_SIGN);
            }
            reqVo.setSearch(search);
        }
        Token account = TokenThreadLocal.getToken();
        return recordService.getUploadList(reqVo, account.getAccountId());
    }

    /**
     * 控制台-媒资管理-音视频管理-重命名
     */
    @TokenAuth
    @Override
    public void rename(@Validated RenameUploadReqVo reqVo) {
        recordService.renameUpload(reqVo);
    }

    /**
     * 控制台-媒资管理-音视频管理-详情
     */
    @TokenAuth
    @Override
    public JSONObject getUploadInfo(@Validated GetUploadInfoReqVo reqVo) {
        return recordService.getUploadInfo(reqVo);
    }

    /**
     * 控制台-媒资管理-音视频管理-详情-删除
     */
    @TokenAuth
    @Override
    public JSONObject deleteVideo(@Validated DeleteVideoReqVo reqVo) {
        return recordService.deleteVideo(reqVo);
    }

    /**
     * 控制台-媒资管理-音视频管理-删除
     */
    @TokenAuth
    @Override
    public JSONObject deleteUpload(@Validated DeleteUploadReqVo reqVo) {
        return recordService.deleteUpload(reqVo);
    }

    /**
     * 控制台-回放管理-在线剪辑-获取回放详情
     */
    @TokenAuth
    @Override
    public GetCutDetailRspVo getCutRecordDetail(@Validated GetCutDetailReqVo reqVo) {
        return recordService.getCutRecordDetail(reqVo);
    }

    @Override
    public List<Object> setWilfullyRecord(SetDefaultRecordReqVo reqVo) {
        recordService.setWilfullyRecord(reqVo);
        return new ArrayList<>();
    }

    /**
     * 回放管理，添加回放
     */
    @TokenAuth
    @Override
    public Boolean add(GetRecordListReqVo reqVo) {
        return recordService.addRecord(reqVo);
    }

    @TokenAuth
    @Override
    public boolean auditRecord(Integer ilId, Integer recordId, Integer auditStatus, String description) {
        return recordService.doAuditRoomRecord(ilId, recordId, auditStatus, description);
    }

    @Override
    @TokenAuth
    public boolean auditRecordSecond(Integer ilId, Integer recordId, Integer auditStatus, String description) {
        return recordService.doAuditRoomRecordSecond(ilId, recordId, auditStatus, description);
    }

    @TokenAuth
    @Override
    public AuditRecordResponseVO getAuditInfo(Integer recordId) {
        return recordService.auditInfo(recordId);
    }

    @TokenAuth
    @Override
    public AuditRecordResponseVO getAuditInfoSecond(Integer recordId) {
        return recordService.auditInfoSecond(recordId);
    }

    @TokenAuth
    @Override
    public GetRecordListRspVo auditList(GetRecordListReqVo reqVo) {
        return recordService.getAuditList(reqVo);
    }

    @TokenAuth
    @Override
    public GetRecordListRspVo auditListSecond(GetRecordListReqVo reqVo) {
        return recordService.getAuditListSecond(reqVo);
    }

    @TokenAuth
    @Override
    public RoomConsoleListRespVO auditRecordRoomList(RoomConsoleListVO reqVO) {
        Token token = TokenThreadLocal.getToken();
        return recordService.auditRoomList(token.getAccountId(), reqVO);
    }




    /**
     * 把秒数转换为时分秒的格式
     */
    private String secToTime(int duration) {
        String timeStr;
        int hour;
        int minute;
        int second;
        if (duration <= 0) {
            return ConstStr.TIME_ZERO;
        } else {
            minute = duration / 60;
            if (minute < 60) {
                second = duration % 60;
                timeStr = "00" + ":" + unitFormat(minute) + ":" + unitFormat(second);
            } else {
                hour = minute / 60;
                if (hour > 99) {
                    return "99:59:59";
                }
                minute = minute % 60;
                second = duration - hour * 3600 - minute * 60;
                timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second);
            }
        }
        return timeStr;

    }

    private String unitFormat(int i) {
        String retStr;
        if (i >= 0 && i < 10) {
            retStr = "0" + i;
        } else {
            retStr = "" + i;
        }
        return retStr;
    }

    private String createSourceName(Integer source) {
        String sourceName;
        switch (source) {
            case 0:
                sourceName = "回放";
                break;
            case 1:
                sourceName = "上传";
                break;
            case 2:
                sourceName = "录制";
                break;
            case 10:
                sourceName = "生成";
                break;
            case 11:
                sourceName = "剪辑";
                break;
            default:
                sourceName = "";

        }
        return sourceName;
    }
}
